package login

import (
	"autoDeploy/config"
	"autoDeploy/dao/myselfMysql"
	"autoDeploy/models"
	"autoDeploy/utils/token"
	"errors"
	"fmt"
	"gorm.io/gorm"
	"strconv"
)

var db, _ = myselfMysql.CreateMySQLClient(config.MysqlDb)

//	Login
//
// 描述信息：处理用户登录和数据库逻辑的校验
//
// Param：
//
//	user ：用户名，密码，手机号
//
// Return：
//
//	uint ：0 登录失败；1 登录成功
//	string: token字符串  或  空
//	error ：错误信息
func Login(user User) (int, string, error) {
	//创建mysql客户端实例
	db, err := myselfMysql.CreateMySQLClient(config.MysqlDb)
	if err != nil {
		return 0, " ", errors.New("login service 创建mysql客户端实例失败" + err.Error())
	}

	//数据库中查询user是否存在
	var foundUser models.User
	result := db.Model(&models.User{}).
		Where("username = ? AND password = ? AND phone = ?", user.Username, user.Password, user.Phone).
		First(&foundUser)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			return 0, " ", errors.New("login service 数据库查询不到用户，用户名、密码或手机号错误")
		}
		return 0, " ", fmt.Errorf("login service 数据库查询失败: %v", result.Error)
	}

	//将token存入redis中 14天后过期
	tokenStr, err := OperateToken(user)

	//销毁mysql客户端
	err = myselfMysql.DestroyMySQLClient(db)
	if err != nil {
		return 0, "", err
	}

	//将UID，role，token返回前端

	return 1, tokenStr, nil

}

// UserData 包含用户信息和角色路由信息的结构体
type UserData struct {
	UserID   uint64             `json:"user_id"`
	Username string             `json:"username"`
	Phone    string             `json:"phone"`
	RoleID   uint64             `json:"role_id"`
	RoleName string             `json:"role_name"`
	Routes   []models.RouteTree `json:"routes"` // 使用树形结构存储路由信息
}

// FetchUserData
//
// 描述信息：查询用户信息，包括用户ID、用户名、手机号、角色ID、角色名称以及所有路由和子路由
//
// Param：
//
//	phone ：用户手机号
//
// Return：
//
//	UserData ：包含用户信息和角色路由信息的结构体
//	error ：错误信息
func FetchUserData(phone string) (UserData, error) {
	// 创建mysql客户端实例
	db, err := myselfMysql.CreateMySQLClient(config.MysqlDb)
	if err != nil {
		return UserData{}, fmt.Errorf("failed to create MySQL client: %w", err)
	}
	defer myselfMysql.DestroyMySQLClient(db) // 确保在函数结束时销毁客户端

	// 查询用户信息
	user, err := models.GetUserByPhone(db, phone)
	if err != nil {
		return UserData{}, fmt.Errorf("failed to get user by phone: %w", err)
	}
	//fmt.Println(user.ID, user.Username, user.Phone)

	// 查询用户对应的系统角色
	userSysRole, err := models.GetUserSysRolesByUserID(db, user.ID)
	if err != nil {
		return UserData{}, fmt.Errorf("failed to get user system role by user ID: %w", err)
	}
	userRoleID := userSysRole.RoleID
	//fmt.Println("用户角色：", userRoleID)

	// 查询角色的所有路由
	routes, err := models.GetSysRoleRoutesBySysRoleID(db, userRoleID)
	if err != nil {
		return UserData{}, fmt.Errorf("failed to get system role routes by role ID: %w", err)
	}
	//fmt.Println("用户角色对应的父级路由：", routes)

	// 提取路由 ID 列表
	var routeIDs []uint64
	for _, route := range routes {
		routeIDs = append(routeIDs, route.RouteID)
	}
	// 获取路由的树形结构
	treeRoutes, err := models.GetSubRoutesByRouteIDs(db, routeIDs)
	if err != nil {
		return UserData{}, fmt.Errorf("failed to get sub routes by route IDs: %w", err)
	}
	//fmt.Println("用户角色对应的路由结构：", treeRoutes)
	// 查询角色名称
	sysRole, err := models.GetSysRoleBySysRoleID(db, userRoleID)
	if err != nil {
		return UserData{}, fmt.Errorf("failed to get system role by role ID: %w", err)
	}

	// 构建返回的用户信息
	userData := UserData{
		UserID:   user.ID,
		Username: user.Username,
		Phone:    user.Phone,
		RoleID:   userRoleID,
		RoleName: sysRole.Name,
		Routes:   treeRoutes,
	}

	return userData, nil
}

//	OperateToken
//
// 描述信息：将用户id和token存入redis
//
// Param：
//
//	user ：用户信息
//
// Return：
//
//	string ：token
//	error ：错误信息
func OperateToken(user User) (string, error) {
	//确定用户的系统角色
	userInfo, err := models.GetUserByPhone(db, user.Phone)
	if err != nil {
		return "", fmt.Errorf("failed to get user by phone: %w", err)
	}
	userSysRole, err := models.GetUserSysRolesByUserID(db, userInfo.ID)
	if err != nil {
		return "", fmt.Errorf("failed to get user system role by user ID: %w", err)
	}

	//创建一个用户token
	tokenStr, err := token.GenerateToken(user.Phone, userSysRole.RoleID)
	if err != nil {
		return " ", err
	}
	//根据用户 手机号 查询 id
	var userID uint64
	db, err := myselfMysql.CreateMySQLClient(config.MysqlDb)
	result := db.Model(&models.User{}).
		Select("id").
		Where("phone = ?", user.Phone).
		First(&userID)
	if result.Error != nil {
		// 处理错误
		return " ", result.Error
	}

	//将用户id和token存入redis
	err = token.AddToken(string(strconv.AppendUint(nil, userID, 10)), tokenStr, config.TokenExpireDuration)
	if err != nil {
		return "", err
	}

	return tokenStr, nil
}
